<?php


/* 
CSS Star Rating Snippet for MODx Content Management Framework (http://modxcms.com)
Copyright (C) 2007 Garry Nutting
*/

/*
 * Generates and handles the processing for a star rating based on the given properties
 */
class rating {

	var $templateVar;
	var $useCookie; //was $onevote
	var $useSession;
	var $documentId;
	var $passedId;
	var $viewOnly;
	var $cssFile;
	var $imgWidth = 25;
	var $cookieExpiry = 604800; //was $ovtime
	var $snippetPath;
	var $starTpl = '[+starRating+]<span class="totalvotes">Votes: [+totalVotes+]</span>';
	var $debug = false;
	var $webGroups = false;
	var $redirect;
	var $lang = 'english';
	var $sessionName;
	var $cookieName;

	var $_templateVarMeta = array ();
	var $_placeholderArray = array ();
	var $_lang = array ();
	var $_debug = '';
	var $_tvId;
	var $_cookieDKey;
	var $_cookiePKey;
	var $_sessionDKey;
	var $_sessionPKey;
	var $_keysObtained = false;

	function rating() {
		$this->__construct();
	}

	function __construct() {
		session_start();
		$this->sessionName = 'starRating';
		$this->cookieName = 'starRating';
	}

	/*
	 * Parses the stored TV value into separated vote statistics
	 */
	function getVote() {
		global $modx;

		$splitVals = array ();
		$this->_templateVarMeta = count($this->_templateVarMeta) == 0 ? $modx->getTemplateVar($this->templateVar, '*', $this->documentId) : $this->_templateVarMeta;
		if (is_array($this->_templateVarMeta) && array_key_exists('value', $this->_templateVarMeta) && preg_match('/^[\d]+:[\d]+$/', $this->_templateVarMeta['value'])) {
			$splitVals = explode(':', $this->_templateVarMeta['value']);
			$this->_templateVarMeta['average'] = $splitVals[0] / $splitVals[1];
			$this->_templateVarMeta['total'] = $splitVals[1];
		} else {
			$this->_templateVarMeta['average'] = 0;
			$this->_templateVarMeta['total'] = 0;
		}
	}

	/*
	 * Checks if a vote has been made and if the vote is valid, stores the vote to the TV
	 */
	function setVote() {
		global $modx;

		$this->__getKeys();
		// check that vote has been cast and is allowed
		if (!isset ($_GET['starvote']) || !isset ($_GET['pid']) || !isset ($_GET['tv'])) {
			return false;
		}
		elseif (isset ($_GET['starvote']) && $this->useCookie == true && array_key_exists($this->_tvId, $this->_cookiePKey)) {
			return false;
		}
		elseif (isset ($_GET['starvote']) && $this->useSession == true && array_key_exists($this->_tvId, $this->_sessionPKey)) {
			return false;
		}
		elseif ($this->passedId <> '' && $this->passedId == $this->documentId && $this->_tvId == $_GET['tv'] && isset ($_GET['starvote']) && is_numeric($_GET['starvote']) && $_GET['starvote'] >= 0 && $_GET['starvote'] <= 5) {
			// get TV value
			$tvValue = $modx->getTemplateVar($this->templateVar, '*', $this->passedId);

			// split out TV values and calculate current Rating
			$splitVals = explode(':', $tvValue['value']);

			$newCount = $splitVals[0] + $_GET['starvote'];
			$newVoteNumber = $splitVals[1] + 1;

			if (!$this->__setTemplateVar("$newCount:$newVoteNumber", $this->passedId, $this->templateVar) && $this->debug) {
				$this->__debug('Unable to save TV Value');
				return false;
			}
			if ($this->useCookie == true) {
				$this->__setKey('cookie');
			}
			if ($this->useSession == true) {
				$this->__setKey('session');
			}
			unset ($_GET);

			// refresh page to show correct ratings
			$curURL = $modx->makeUrl($this->redirect);
			$modx->sendRedirect($curURL);
		}
	}

	/*
	 * Renders the vote for screen output
	 */
	function renderVote() {
		global $modx;

		if ($this->documentId) {
			$this->__getLang();
			$this->getVote();

			if (!$this->__disallowVoting()) {
				$this->_placeholderArray['starRating'] = "<ul class='star-rating'>
																						<li class='current-rating' style='width:" . $this->imgWidth * $this->_templateVarMeta['average'] . "px;'>" . $this->_lang['current_1'] . round($this->_templateVarMeta['average'], 1) . $this->_lang['current_2'] . "</li>
																						<li><a href='" . $modx->makeUrl($modx->documentObject['id'], '', 'starvote=1&amp;pid=' . $this->documentId . '&amp;tv=' . $this->_tvId) . "' title='" . $this->_lang['one_star'] . "' class='one-star'>1</a></li>
																						<li><a href='" . $modx->makeUrl($modx->documentObject['id'], '', 'starvote=2&amp;pid=' . $this->documentId . '&amp;tv=' . $this->_tvId) . "' title='" . $this->_lang['two_stars'] . "' class='two-stars'>2</a></li>
																						<li><a href='" . $modx->makeUrl($modx->documentObject['id'], '', 'starvote=3&amp;pid=' . $this->documentId . '&amp;tv=' . $this->_tvId) . "' title='" . $this->_lang['three_stars'] . "' class='three-stars'>3</a></li>
																						<li><a href='" . $modx->makeUrl($modx->documentObject['id'], '', 'starvote=4&amp;pid=' . $this->documentId . '&amp;tv=' . $this->_tvId) . "' title='" . $this->_lang['four_stars'] . "' class='four-stars'>4</a></li>
																						<li><a href='" . $modx->makeUrl($modx->documentObject['id'], '', 'starvote=5&amp;pid=' . $this->documentId . '&amp;tv=' . $this->_tvId) . "' title='" . $this->_lang['five_stars'] . "' class='five-stars'>5</a></li>
																						</ul>";
			} else {
				$this->_placeholderArray['starRating'] = "<ul class='star-rating'>
																						<li class='current-rating' style='width:" . $this->imgWidth * $this->_templateVarMeta['average'] . "px;'>" . $this->_lang['current_1'] . round($this->_templateVarMeta['average'], 1) . $this->_lang['current_2'] . "</li>
																						<li class='one-star'>1</li>
																						<li class='two-stars'>2</li>
																						<li class='three-stars'>3</li>
																						<li class='four-stars'>4</li>
																						<li class='five-stars'>5</li>
																						</ul>";
			}

			$this->_placeholderArray['totalVotes'] = $this->_templateVarMeta['total'];

			foreach ($this->_placeholderArray as $n => $v) {
				$this->starTpl = str_replace('[+' . $n . '+]', $v, $this->starTpl);
			}
			$output = '';
			$output .= $this->starTpl;
			return $output;
		} else {
			$this->__debug('Unable to render star rating, documentId is not set');
			return false;
		}
	}

	/*
	 * Outputs the CSS using the $modx->regClientCSS() method
	 */
	function outputCSS() {
		global $modx;
		if ($this->cssFile != null) {
			$modx->regClientCSS($this->cssFile);
		} else {
			$this->__debug('Unable to output the CSS');
			return false;
		}
	}

	/*
	 * Loads the language file for use in the class
	 */
	function __getLang() {
		global $modx;
		$_lang = array ();
		include $modx->config['base_path'] . 'assets/snippets/star_rating/lang/english.inc.php';
		if ($this->lang && file_exists($modx->config['base_path'] . 'assets/snippets/star_rating/lang/' . $this->lang . '.inc.php')) {
			include $modx->config['base_path'] . 'assets/snippets/star_rating/lang/' . $this->lang . '.inc.php';
		}
		$this->_lang = $_lang;
	}

	/*
	 * Sets the template variable based on the values passed into the method
	 */
	function __setTemplateVar($value, $docID, $tplVarName) {
		global $modx;

		// get tmplvar id
		$tplName = $modx->getFullTableName('site_tmplvars');
		$tplRS = $modx->db->select('id', $tplName, 'name="' . $tplVarName . '"');
		$tplRow = $modx->db->getRow($tplRS);

		$tblName = $modx->getFullTableName('site_tmplvar_contentvalues');

		$selectQuery = $modx->db->select('*', $tblName, 'contentid=' . $docID . ' AND tmplvarid=' . $tplRow['id']);

		$updFields = array (
			'value' => $value
		);
		$insFields = array (
			'tmplvarid' => $tplRow['id'],
			'contentid' => $docID,
			'value' => $value
		);

		// check if record needs to be inserted or updated
		if ($modx->db->getRecordCount($selectQuery) < 1) {
			$modx->db->insert($insFields, $tblName);
		} else {
			$modx->db->update($updFields, $tblName, 'contentid=' . $docID . ' AND tmplvarid=' . $tplRow['id']);
		}
	}

	/*
	 * Checks permissions and properties to see if voting is disallowed
	 */
	function __disallowVoting() {
		if ($this->webGroups !== false && $this->__checkMembership() == false) {
			return true;
		}
		if (!$this->_keysObtained) {
			$this->__getKeys();
		}
		if ($this->useCookie == true && array_key_exists($this->_tvId, $this->_cookieDKey)) {
			$this->viewOnly = true;
			return true;
		}
		elseif ($this->useSession == true && array_key_exists($this->_tvId, $this->_sessionDKey)) {
			$this->viewOnly = true;
			return true;
		} else {
			$this->viewOnly = $this->viewOnly ? $this->viewOnly : false;
			return false;
		}
	}

	/*
	 * Check if the user is allowed to vote based on web group membership (only if webGroups property has been set)
	 */
	function __checkMembership() {
		global $modx;
		$permGranted = false;

		if ($this->webGroups !== false && isset ($_SESSION['webInternalKey'])) {
			$groupArray = explode(',', $this->webGroups);
			if (count($groupArray) > 0) {
				foreach ($groupArray as $k => $v) {
					$groupArray[$k] = trim($v);
				}
				$tbl = $modx->getFullTableName('webgroup_names');
				$tbl2 = $modx->getFullTableName('web_groups');
				$sql = "SELECT wgn.name FROM $tbl wgn INNER JOIN $tbl2 wg ON wg.webgroup=wgn.id AND wg.webuser='" . $_SESSION['webInternalKey'] . "'";
				$rs = $modx->db->query($sql);
				if ($modx->db->getRecordCount($rs) > 0) {
					while ($row = $modx->db->getRow($rs)) {
						if (in_array($row['name'], $groupArray)) {
							$permGranted = true;
						}
					}
				}
			}
		} else {
			$permGranted = true;
		}
		return $permGranted;
	}

	/*
	 * Get the session and cookie keys
	 */
	function __getKeys() {
		global $modx;
		if (!isset ($this->_tvId)) {
			$this->_tvId = $modx->db->getValue('SELECT id FROM ' . $modx->getFullTableName('site_tmplvars') . ' WHERE name=\'' . $this->templateVar . '\'');
		}
		if (isset ($_SESSION[$this->sessionName]) && array_key_exists($this->passedId, $_SESSION[$this->sessionName])) {
			$this->_sessionPKey = unserialize($_SESSION[$this->sessionName][$this->passedId]);
		} else {
			$this->_sessionPKey = array ();
		}
		if ($this->passedId == $this->documentId) {
			$this->_sessionDKey = & $this->_sessionPKey;
		} else {
			if (isset ($_SESSION[$this->sessionName]) && array_key_exists($this->documentId, $_SESSION[$this->sessionName])) {
				$this->_sessionDKey = unserialize($_SESSION[$this->sessionName][$this->documentId]);
			} else {
				$this->_sessionDKey = array ();
			}
		}

		if (array_key_exists($this->cookieName, $_COOKIE)) {
			$cArray = unserialize($_COOKIE[$this->cookieName]);
			if (array_key_exists($this->passedId, $cArray)) {
				$this->_cookiePKey = $cArray[$this->passedId];
			} else {
				$this->_cookiePKey = array ();
			}
		} else {
			$this->_cookiePKey = array ();
		}
		if ($this->_passedId == $this->documentId) {
			$this->_cookieDKey = & $this -_cookiePKey;
		} else {
			if (array_key_exists($this->cookieName, $_COOKIE)) {
				$cArray = unserialize($_COOKIE[$this->cookieName]);
				if (array_key_exists($this->documentId, $cArray)) {
					$this->_cookieDKey = $cArray[$this->documentId];
				} else {
					$this->_cookieDKey = array ();
				}
			} else {
				$this->_cookieDKey = array ();
			}
		}
		$this->_keysObtained = true;
	}

	/*
	 * Set the cookie or session values to their required values
	 */
	function __setKey($type) {
		switch ($type) {
			case 'session' :
				$this->_sessionPKey[$this->_tvId] = '1';
				$_SESSION[$this->sessionName][$this->passedId] = serialize($this->_sessionPKey);
				session_write_close();
				return true;
			case 'cookie' :
				$this->_cookiePKey[$this->_tvId] = '1';
				$cArray = unserialize($_COOKIE[$this->cookieName]);
				$cArray[$this->passedId] = $this->_cookiePKey;
				setcookie($this->cookieName, serialize($cArray), time() + $this->cookieExpiry);
				return true;
		}
	}

	/*
	 * Simple debug output method
	 */
	function __debug($message) {
		$this->_debug .= '<p>' . $message . '</p>';
	}
}
?>